package qqsdk

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strings"
	"time"

	"gitee.com/ands11/utils/gorequest"
)

type HttpParams = map[string]string
type HttpResponse struct {
	http.Response
	Text string
}

func NewHttpRequest() *HttpRequest {
	h := HttpRequest{
		agent:   gorequest.New(),
		headers: HttpParams{},
	}
	return &h
}

type HttpRequest struct {
	agent     *gorequest.SuperAgent
	resp      HttpResponse
	userAgent string
	referer   string
	url       string
	proxy     string
	headers   HttpParams
}

func (p *HttpRequest) SetProxy(proxy string) {
	p.proxy = proxy
}

func (p *HttpRequest) SetUrl(url string) {
	p.url = url
}

func (p *HttpRequest) SetReferer(uri string) {
	p.referer = uri
}

func (p *HttpRequest) SetUserAgent(userAgent string) {
	p.userAgent = userAgent
}

func (p *HttpRequest) AddHeader(key string, value string) {
	p.headers[key] = value
}

func (p *HttpRequest) AddCookie(uri string, cookie *http.Cookie) {
	cookieURL, _ := url.Parse(uri)
	var cookies []*http.Cookie //= p.agent.Client.Jar.Cookies(cookieURL)

	cookies = append(cookies, cookie)
	p.agent.Client.Jar.SetCookies(cookieURL, cookies)
}

func (p *HttpRequest) BodyToString() string {
	buf := new(bytes.Buffer)
	buf.ReadFrom(p.resp.Body)
	s := buf.String()
	return s
}

func (p *HttpRequest) BodyToMap() map[string]interface{} {
	var ret map[string]interface{}
	text := p.BodyToString()
	//fmt.Println(text)
	err := json.Unmarshal([]byte(text), &ret)
	if err != nil {
		ret = map[string]interface{}{
			"errno":  float64(400),
			"errmsg": "网络错误",
		}
	}
	ret["errno"] = int(ret["errno"].(float64))
	return ret
}

// par 查询参数 pars, headers: 请求头,空将使用设置的默认headers
func (p *HttpRequest) Get(uri string, par HttpParams, headers ...HttpParams) HttpResponse {
	if p.agent == nil {
		p.agent = gorequest.New()
	}
	if len(par) > 0 {
		//使用url.Parse()函数将字符串解析成*url.URL类型。
		//如果URL已经是url.URL类型可以跳过这一步。
		urlA, err := url.Parse(uri)
		if err != nil {
			log.Fatal(err)
		}

		//使用Query()方法获取URL中的查询字符串参数，存在map类型中。
		values := urlA.Query()

		//使用Add(), Set(), Del()方法来修改返回查询参数, 本质上就是对map的修改
		//可以使用Get(), Has()方法来查询或检查是否包含对应参数
		//values.Add("occupation", "carpenter")
		//values.Del("gender")
		for key, value := range par {
			values.Set(key, fmt.Sprintf("%v", value))
		}
		//使用Encode()方法将map转为URL格式的字符串（类似"age=29&name=alice...")
		//然后将新的查询参数赋值到URL对象的查询参数字段
		urlA.RawQuery = values.Encode()
		uri = urlA.String()
		//fmt.Printf("urlA: %s", urlA.String())
	}
	if strings.Index(uri, "/") == 0 {
		uri = p.url + uri
	}
	p.agent.Proxy(p.proxy).Get(uri)
	if len(headers) > 0 {
		for k, v := range headers[0] {
			p.agent.Set(k, fmt.Sprintf("%v", v))
		}
	} else {
		for k, v := range p.headers {
			p.agent.Set(k, fmt.Sprintf("%v", v))
		}
		p.agent.Set("user-agent", p.userAgent)
	}
	p.agent.Set("referer", p.referer)
	p.agent.Retry(3, 5*time.Second, http.StatusBadRequest, http.StatusInternalServerError)
	resp, text, _ := p.agent.End()
	if resp == nil {
		p.resp = HttpResponse{
			Response: http.Response{
				StatusCode: 0,
				Status:     "发送请求失败",
			},
			Text: "",
		}
	} else {
		p.resp.Response = *resp
		p.resp.Text = text
	}
	return p.resp
}

// postData post提交参数 headers 1 请求头
func (p *HttpRequest) Post(uri string, postData interface{}, headers ...HttpParams) HttpResponse {
	if p.agent == nil {
		p.agent = gorequest.New()
	}
	if strings.Index(uri, "/") == 0 {
		uri = p.url + uri
	}
	p.agent.Proxy(p.proxy).Post(uri)
	if len(headers) > 0 {
		for k, v := range headers[0] {
			p.agent.Set(k, fmt.Sprintf("%v", v))
		}
	} else {
		for k, v := range p.headers {
			p.agent.Set(k, fmt.Sprintf("%v", v))
		}
		p.agent.Set("user-agent", p.userAgent)
	}
	p.agent.Set("referer", p.referer)
	p.agent.Retry(3, 5*time.Second, http.StatusBadRequest, http.StatusInternalServerError, http.StatusRequestTimeout, http.StatusGatewayTimeout)
	switch postData.(type) {
	case string:
		p.agent.SendString(postData.(string))
	case map[string]interface{}:
		p.agent.SendMap(postData)
	default:
		p.agent.Send(postData)
	}

	resp, text, _ := p.agent.End()
	if resp == nil {
		p.resp = HttpResponse{
			Response: http.Response{
				StatusCode: 0,
				Status:     "发送请求失败",
			},
			Text: "",
		}
	} else {
		p.resp.Response = *resp
		p.resp.Text = text
	}
	return p.resp
}
